home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Atari Mega Archive 2
/
Atari Mega Archive CD - Volume 2.iso
/
minix
/
up1510b.tgz
/
up1510b
/
src
/
commands
/
tar.c
< prev
next >
Wrap
C/C++ Source or Header
|
1990-07-23
|
22KB
|
907 lines
/* tar - tape archiver Author: Michiel Huisjes */
/* Usage: tar [cxt][vo][F][f] tapefile [files]
*
* attempt to make tar to conform to POSIX 1003.1
* disclaimer: based on an old (1986) POSIX draft.
* Klamer Schutte, 20/9/89
*
* Changes:
* Changed to handle the original minix-tar format. KS 22/9/89
* Changed to handle BSD4.3 tar format. KS 22/9/89
* Conform to current umask if not super-user. KS 22/9/89
* Update usage message to show f option KS 22/9/89
*
*
* 1) tar will back itself up, should check archive inode num(&dev) and
then check the target inode number. In verbose mode, issue
warning, in all cases ignore target.
marks@mgse Mon Sep 25 10:38:58 CDT 1989
added global varaibles, made changes to main() and add_file();
maks@mgse Mon Sep 25 12:09:20 CDT 1989
2) tar will not notice that a file has changed size while it was being
backed up. should issue warning.
marks@mgse Mon Sep 25 10:38:58 CDT 1989
3) the 'f' option was not documented in usage[].
marks@mgse Mon Sep 25 12:03:20 CDT 1989
changed both usage[] defines. Why are there two (one is commented out)?
( deleted by me (was done twice) -- KS, 2/10/89 )
*
* changed stat on tar_fd to an fstat KS 2/10/89
* deleted mkfifo() code -- belongs in libc.a KS 2/10/89
* made ar_dev default to -1 : an illegal device KS 2/10/89
* made impossible to chown if normal user KS 2/10/89
* if names in owner fields not known use numirical values KS 2/10/89
* creat with mask 666 -- use umask if to liberal KS 2/10/89
* allow to make directories as ../directory KS 2/10/89
* allow tmagic field to end with a space (instead of \0) KS 2/10/89
* correct usage of tmagic field KS 3/10/89
* made mkdir() to return a value if directory == "." KS 3/10/89
* made lint complains less (On a BSD 4.3 system) KS 3/10/89
* use of directory(3) routines KS 3/10/89
* deleted use of d_namlen selector of struct dirent KS 18/10/89
*
* Bugs:
* verbose mode is not reporting consistent
* code needs cleanup
* prefix field is not used
* timestamp of a directory will not be correct if there are files to be
* unpacked in the directory
* (add you favorite bug here (or two (or three (or ...))))
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <pwd.h>
#include <grp.h>
#include <tar.h>
#include <stdio.h> /* need NULL */
#define POSIX_COMP /* POSIX compatible */
#define DIRECT_3 /* use directory(3) routines */
#ifdef DIRECT_3
#ifndef BSD
/* To all minix users: i am sorry, developed this piece of code on a
* BSD system. KS 18/10/89 */
#include <dirent.h>
#define direct dirent /* stupid BSD non-POSIX compatible name! */
#else /* BSD */
#include <sys/dir.h>
#include <dir.h>
#endif /* BSD */
#endif /* DIRECT_3 */
#ifdef S_IFIFO
#define HAVE_FIFO /* have incorporated Simon Pooles' changes */
#endif
typedef char BOOL;
#define TRUE 1
#define FALSE 0
#define HEADER_SIZE TBLOCK
#define NAME_SIZE NAMSIZ
/* #define BLOCK_BOUNDARY 20 -- not in POSIX ! */
typedef union hblock HEADER;
/* Make the MINIX member names overlap to the POSIX names */
#define m_name name
#define m_mode mode
#define m_uid uid
#define m_gid gid
#define m_size size
#define m_time mtime
#define m_checksum chksum
#define m_linked typeflag
#define m_link linkname
#define hdr_block dummy
#define m header
#define member dbuf
#if 0 /* original structure -- see tar.h for new
* structure */
typedef union {
char hdr_block[HEADER_SIZE];
struct m {
char m_name[NAME_SIZE];
char m_mode[8];
char m_uid[8];
char m_gid[8];
char m_size[12];
char m_time[12];
char m_checksum[8];
char m_linked;
char m_link[NAME_SIZE];
} member;
} HEADER;
#endif
/* Structure used to note links */
struct link {
ino_t ino;
dev_t dev;
char name[NAMSIZ];
struct link *next;
} *link_top = NULL;
HEADER header;
#define INT_TYPE (sizeof(header.member.m_uid))
#define LONG_TYPE (sizeof(header.member.m_size))
#define MKDIR "/bin/mkdir"
#define NIL_HEADER ((HEADER *) 0)
#define NIL_PTR ((char *) 0)
#define BLOCK_SIZE TBLOCK
#define flush() print(NIL_PTR)
BOOL show_fl, creat_fl, ext_fl;
int tar_fd;
/* Char usage[] = "Usage: tar [cxt] tarfile [files]."; */
char usage[] = "Usage: tar [cxt][vo][F][f] tarfile [files].";
char io_buffer[BLOCK_SIZE];
char path[NAME_SIZE];
char pathname[NAME_SIZE];
int force_flag = 0;
#ifdef ORIGINAL_DEFAULTS
int chown_flag = 1;
int verbose_flag = 1;
#else
int chown_flag = 0;
int verbose_flag = 0;
#endif
/* Make sure we don't tar ourselves. marks@mgse Mon Sep 25 12:06:28 CDT 1989 */
ino_t ar_inode; /* archive inode number */
dev_t ar_dev; /* archive device number */
int total_blocks;
int u_mask; /* one's complement of current umask */
long convert();
#define block_size() (int) ((convert(header.member.m_size, LONG_TYPE) \
+ (long) BLOCK_SIZE - 1) / (long) BLOCK_SIZE)
error(s1, s2)
char *s1, *s2;
{
string_print(NIL_PTR, "%s %s\n", s1, s2 ? s2 : "");
flush();
exit(1);
}
BOOL get_header();
main(argc, argv)
int argc;
register char *argv[];
{
register char *mem_name;
register char *ptr;
struct stat st;
int i;
if (argc < 3) error(usage, NIL_PTR);
for (ptr = argv[1]; *ptr; ptr++) {
switch (*ptr) {
case 'c': creat_fl = TRUE; break;
case 'x': ext_fl = TRUE; break;
case 't': show_fl = TRUE; break;
case 'v': /* verbose output -Dal */
verbose_flag = !verbose_flag;
break;
case 'o': /* chown/chgrp files -Dal */
chown_flag = TRUE;
break;
case 'F': /* IGNORE ERRORS -Dal */
force_flag = TRUE;
break;
case 'f': /* standard U*IX usage -KS */
break;
default: error(usage, NIL_PTR);
}
}
if (creat_fl + ext_fl + show_fl != 1) error(usage, NIL_PTR);
if (strcmp(argv[2], "-") == 0)/* only - means stdin/stdout - KS */
tar_fd = creat_fl ? 1 : 0; /* '-' means used
* stdin/stdout -Dal */
else
tar_fd = creat_fl ? creat(argv[2], 0666) : open(argv[2], O_RDONLY);
if (tar_fd < 0) error("Cannot open ", argv[2]);
if (geteuid()) { /* check if super-user */
int save_umask;
save_umask = umask(0);
u_mask = ~save_umask;
umask(save_umask);
chown_flag = TRUE; /* normal user can't chown */
} else
u_mask = 0777; /* don't restrict if 'privileged utiliy' */
ar_dev = -1; /* impossible device nr */
if (creat_fl) {
if (tar_fd > 1 && fstat(tar_fd, &st) < 0)
error("Can't stat ", argv[2]); /* will never be here,
* right? */
else { /* get archive inode & device */
ar_inode = st.st_ino; /* save files inode */
ar_dev = st.st_dev; /* save files device */
} /* marks@mgse Mon Sep 25 11:30:45 CDT 1989 */
for (i = 3; i < argc; i++) {
add_file(argv[i]);
path[0] = '\0';
}
adjust_boundary();
} else if (ext_fl) {
/* extraction code moved here from tarfile() MSP */
while (get_header()) {
mem_name = header.member.m_name;
if (is_dir(mem_name)) {
for (ptr = mem_name; *ptr; ptr++);
*(ptr - 1) = '\0';
header.dbuf.typeflag = '5';
}
for (i = 3; i < argc; i++)
if (!strncmp(argv[i], mem_name, strlen(argv[i])))
break;
if (argc == 3 || (i < argc)) {
extract(mem_name);
} else
if (header.dbuf.typeflag == '0' ||
header.dbuf.typeflag == 0 ||
header.dbuf.typeflag == ' ')
skip_entry();
flush();
}
} else
tarfile(); /* tarfile() justs prints info. now MSP */
flush();
exit(0);
}
BOOL get_header()
{
register int check;
mread(tar_fd, (char *) &header, sizeof(header));
if (header.member.m_name[0] == '\0') return FALSE;
if (force_flag) /* skip checksum verification -Dal */
return TRUE;
check = (int) convert(header.member.m_checksum, INT_TYPE);
if (check != checksum()) error("Tar: header checksum error.", NIL_PTR);
return TRUE;
}
/* tarfile() just lists info about archive now; as of the t flag. */
/* Extraction has been moved into main() as that needs access to argv[] */
tarfile()
{
register char *ptr;
register char *mem_name;
while (get_header()) {
mem_name = header.member.m_name;
string_print(NIL_PTR, "%s%s", mem_name,
(verbose_flag ? " " : "\n"));
switch (header.dbuf.typeflag) {
case '1':
verb_print("linke